#include "threadPool.h"

int cmd_cd(int netfd, cmd_t Cmd)
{
    // 以下为分割地址用
    char *temp[20] = {0};
    int i = 0;
    char s[100] = {0};
    // check为报错标志
    int check = 0;
    int user_id = client_id[netfd];
    // 不支持以"/"开头的路径
    if (Cmd.object[0] == '/')
    {
        check = 1; // 发送1给服务端报错
        send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    // 获取用户当前文件夹code与pwd
    char pwd[1024] = {0};
    get_user_pwd(user_id, pwd);
    int code;
    int parent_code;
    get_user_code(user_id, &code);
    parent_code = code;

    if (strcmp(Cmd.object, "..") == 0 || strcmp(Cmd.object, "../") == 0)
    {
        if (code == 0)
        { // 已在根目录，不能返回
            check = 1;
            send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
            return 0;
        }
        // 更新code为其父目录的code
        get_parent_id(code, &parent_code);
        code = parent_code;
        // 更新pwd
        strcpy(s, pwd);
        temp[i] = strtok(s, "/");
        ++i;
        while ((temp[i] = strtok(NULL, "/")) != NULL)
        {
            ++i;
        }
        bzero(pwd, sizeof(pwd));
        for (int j = 0; j < i - 1; ++j)
        {
            strcat(pwd, temp[j]);
            strcat(pwd, "/");
        }
    }

    else if (strcmp(Cmd.object, "~/") == 0 || strcmp(Cmd.object, "~") == 0)
    { // 返回根目录
        code = 0;
        strcpy(pwd, "~/");
    }

    else
    {
        bzero(s, sizeof(s));
        bzero(temp, sizeof(temp));
        strcpy(s, Cmd.object);
        temp[i] = strtok(s, "/");
        ++i;
        while ((temp[i] = strtok(NULL, "/")) != NULL)
        {
            ++i;
        }
        for (int j = 0; j < i; ++j)
        {
            if (strcmp(temp[j], ".") == 0)
            {
                continue;
            }
            if (strcmp(temp[j], "..") == 0)
            {
                if (code == 0)
                { // 已经在根目录，不能返回上级
                    check = 1;
                    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                    return 0;
                }
                get_parent_id(code, &parent_code);
                code = parent_code;
                // 更新pwd
                char str[100] = {0};
                char *temp_2[20] = {0};
                int a = 0;
                strcpy(str, pwd);
                temp_2[a] = strtok(str, "/");
                ++a;
                while ((temp_2[a] = strtok(NULL, "/")) != NULL)
                {
                    ++a;
                }
                bzero(pwd, sizeof(pwd));
                for (int b = 0; b < a - 1; ++b)
                {
                    strcat(pwd, temp_2[b]);
                    strcat(pwd, "/");
                }
                continue;
            }
            if (strcmp(temp[j], "~") == 0)
            {
                parent_code = code = 0;
                continue;
            }
            char type[2] = {0};
            int ret = get_file_code(user_id, temp[j], &code, parent_code, type);
            if (ret != 0 || strcmp(type, "d") != 0)
            { // 路径不存在或目的地不是目录文件
                check = 1;
                send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                return 0;
            }
            if (parent_code != 0)
            {
                strcat(pwd, "/");
            }
            strcat(pwd, temp[j]);
            parent_code = code;
        }
    }
    update_user_path(user_id, pwd, code);
    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
    train_t train;
    train.length = strlen(pwd);
    send(netfd, &train.length, sizeof(train.length), MSG_NOSIGNAL);
    strcpy(train.data, pwd);
    send(netfd, train.data, train.length, MSG_NOSIGNAL);
    return 0;
}

int cmd_ls(int netfd, cmd_t Cmd)
{
    int code, parent_code;
    int check = 0;
    int user_id = client_id[netfd];
    char type[2];
    get_user_code(user_id, &code); // 获得当前所在目录的id
    parent_code = code;
    // 不支持以"/"开头的路径
    if (Cmd.object[0] == '/')
    {
        check = 1; // 发送1给服务端报错
        send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    if (strlen(Cmd.object) == 0 || strcmp(Cmd.object, ".") == 0 || strcmp(Cmd.object, "./") == 0)
    {
        // code不用改变
        printf("local!\n");
    }
    else // 与cd一样的判断
    {
        char pwd[1024] = {0};
        get_user_pwd(user_id, pwd);
        char *words[20] = {0};
        int i = 0;
        char s[100] = {0};
        // 是..的情况
        if (strcmp(Cmd.object, "..") == 0 || strcmp(Cmd.object, "../") == 0)
        {
            if (code == 0) // 已经在根目录，不能返回上级
            {
                check = 1;
                send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                return 0;
            }
            get_parent_id(code, &parent_code);
            code = parent_code;
        }
        // 不是..就去往目的地址
        else
        {
            // 将目标地址切分
            bzero(s, sizeof(s));
            bzero(words, sizeof(words));
            strcpy(s, Cmd.object);
            words[i] = strtok(s, "/");
            ++i;
            while ((words[i] = strtok(NULL, "/")) != NULL)
            {
                ++i;
            }

            for (int j = 0; j < i; ++j)
            {
                if (strcmp(words[j], ".") == 0)
                {
                    continue;
                }
                if (strcmp(words[j], "~") == 0) // 如果以根目录开始，则改变code值为0
                {
                    parent_code = code = 0;
                    continue;
                }
                if (strcmp(words[j], "..") == 0)
                {
                    if (code == 0) // 已经在根目录，不能返回上级
                    {
                        check = 1;
                        send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                        return 0;
                    }
                    get_parent_id(code, &parent_code);
                    code = parent_code;
                    continue;
                }
                // printf("%s\n", words[j]);
                char type[2];
                int ret = get_file_code(user_id, words[j], &code, parent_code, type); // 获取当前文件在虚拟文件目录的id和类型
                if (ret != 0 || strcmp(type, "d") != 0)                               // 文件查找失败；不是目录文件；不在可搜索路径下
                {
                    check = 1;
                    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                    return 0;
                }
                parent_code = code; // 继续往下遍历，遍历结束code就是要浏览的目录的文件id
            }
        }
    }
    // printf("code = %d\n", code);
    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
    find_code_files(netfd, code, user_id); // 把找到的文件发给客户端
}

int cmd_pwd(int netfd, cmd_t Cmd)
{
    int user_id = client_id[netfd];
    char pwd[1024] = {0};
    get_user_pwd(user_id, pwd);
    send(netfd, pwd, strlen(pwd), MSG_NOSIGNAL);
    // printf("pwd is done!\n");
    return 0;
}

int cmd_remove(int netfd, cmd_t Cmd)
{
    int user_id = client_id[netfd];
    int code;
    int parent_code;
    char type[2] = {0};
    char file[100] = {0};
    int check = 0;
    get_user_code(user_id, &code);
    parent_code = code;
    if (Cmd.object[0] == '/' || strcmp(Cmd.object, ".") == 0 || strcmp(Cmd.object, "~/") == 0 || strcmp(Cmd.object, "./") == 0 || strcmp(Cmd.object, "..") == 0 || strcmp(Cmd.object, "../") == 0)
    { // 以上情况不支持
        check = 1;
        send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    else
    {
        // 将目标地址切分
        char *words[20] = {0};
        int i = 0;
        char s[100] = {0};
        strcpy(s, Cmd.object);
        words[i] = strtok(s, "/");
        ++i;
        while ((words[i] = strtok(NULL, "/")) != NULL)
        {
            ++i;
        }
        for (int j = 0; j < i; ++j)
        {
            if (strcmp(words[j], ".") == 0)
            {
                continue;
            }
            if (strcmp(words[j], "~") == 0)
            {
                parent_code = code = 0;
                continue;
            }
            if (strcmp(words[j], "..") == 0)
            {
                if (code == 0) // 已经在根目录，不能返回上级
                {
                    check = 1;
                    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                    return 0;
                }
                get_parent_id(code, &parent_code);
                code = parent_code;
                continue;
            }
            // printf("%s\n", words[j]);
            int ret = get_file_code(user_id, words[j], &code, parent_code, type); // 获取当前文件在虚拟文件目录的id和类型
            // printf("ret = %d\n", ret);
            if (ret != 0) // 路径错误
            {
                check = 1;
                send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
                return 0;
            }
            if (j != i - 1)
            {
                parent_code = code; // 继续往下遍历，遍历结束code就是要浏览的目录的文件id
            }
        }
        strcpy(file, words[i - 1]);
    }
    if (code == 0)
    {
        check = 1;
        send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    // printf("code = %d\n", code);
    if (strcmp(type, "f") == 0)
    {
        char md5_str[MD5_STR_LEN + 1] = {0};
        get_fsystem_md5(file, user_id, parent_code, md5_str); // 要先查询再删除
        minus_file_link(md5_str);                             // 本地链接数减一
    }
    if (strcmp(type, "d") == 0)
    { // 如果删除目录则需使该目录下所有文件的链接数减一
        MYSQL *db;
        mysqlconnect(&db);
        minus_dir_link(&db, user_id, code);
    }
    del_fsystem_file(code, user_id);
    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
    return 0;
}

int cmd_gets(int netfd, cmd_t Cmd)
{
    transFile(netfd, Cmd);
    return 0;
}

int cmd_puts(int netfd, cmd_t Cmd)
{
    // 若是上传命令，则搭建第二条tcp连接
    int user_id = client_id[netfd];
    int sockfd_2;
    tcpInit("./config/server_2.conf", &sockfd_2);
    int netfd_2 = accept(sockfd_2, NULL, NULL);
    printf("the second connection established!\n");
    int ret = recvFile(netfd_2, user_id);
    close(netfd_2);
    close(sockfd_2);
    return 0;
}

int cmd_mkdir(int netfd, cmd_t Cmd)
{
    int user_id = client_id[netfd];
    int code;
    int check = 0;
    get_user_code(user_id, &code);
    int test;
    char type[2] = {0};
    int ret = get_file_code(user_id, Cmd.object, &test, code, type);
    if (ret == 0) // 说明该名称的文件夹已经存在
    {
        check = 1;
        send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
        return 0;
    }
    check = add_fsystem_dir(code, Cmd.object, user_id);
    send(netfd, &check, sizeof(check), MSG_NOSIGNAL);
    return 0;
}
